#include "File.h"


File::File(void)
	:hFile(0), dwCreationDisposition(0), dwDesiredAccess(0), dwShareMode(0), dwFlagsAndAttributes(0), opened(false)
{

}

File::File(const char* filename, FileMode mode)
	:hFile(0), dwCreationDisposition(0), dwDesiredAccess(0), dwShareMode(0), dwFlagsAndAttributes(0), opened(false)
{
	Open(filename, mode);
}
	
File::File(std::string filename, FileMode mode)
	:hFile(0), dwCreationDisposition(0), dwDesiredAccess(0), dwShareMode(0), dwFlagsAndAttributes(0), opened(false)
{
	Open(filename, mode);
}

File::~File(void)
{
	if(hFile != NULL)
	{
		CloseHandle(hFile);
	}
}

void File::CreateFlags(FileMode mode)
{
	dwCreationDisposition = 0;
	dwDesiredAccess = 0;
	dwFlagsAndAttributes = 0;
	dwShareMode = 0;

	if(mode == FILE_READ)
	{
		dwDesiredAccess = GENERIC_READ;
		dwShareMode = FILE_SHARE_READ;
		dwCreationDisposition = OPEN_EXISTING;
		dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
	}

	if(mode == FILE_WRITE)
	{
		dwDesiredAccess = GENERIC_WRITE;
		dwShareMode = FILE_SHARE_READ;
		dwCreationDisposition = CREATE_ALWAYS;
		dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
	}
}

bool File::Open(const char* filename, FileMode mode)
{
	opened = true;

	CreateFlags(mode);

	hFile = CreateFileA(filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL);

	if(hFile == INVALID_HANDLE_VALUE)
	{
		Con::Printf("Error! Failed to open %s \n", filename);
		opened = false;
	}
	
	return opened;
}


bool File::Open(std::string filename, FileMode mode)
{
	return Open(filename.c_str(), mode);
}


void File::Close()
{
	CloseHandle(hFile);
	hFile = NULL;
	opened = false;
	dwCreationDisposition = 0;
	dwDesiredAccess = 0;
	dwFlagsAndAttributes = 0;
	dwShareMode = 0;
}

u32 File::GetSize() const
{
	if(hFile != NULL || hFile != INVALID_HANDLE_VALUE)
	{
		return (u32)GetFileSize(hFile, NULL);
	}

	return 0;
}

HANDLE File::GetHandle() const
{
	if(opened == true)
	{
		return hFile;
	}

	return 0;
}

u32 File::Read(u8* buffer, u32 bytes)
{
	DWORD readed = 0;

	if(opened == true && dwDesiredAccess == GENERIC_READ)
	{
		if(!ReadFile(hFile, (LPVOID*)buffer, bytes, &readed, NULL))
			Con::Write("Cannot read file \n");
	}

	return readed;
}

u32 File::Write(const u8* buffer, u32 bytes)
{
	DWORD writed;

	if(opened == true && dwDesiredAccess == GENERIC_WRITE)
	{
		if(!WriteFile(hFile, (LPCVOID*)buffer, bytes, &writed, NULL))
			Con::Write("Cannot write file \n");
	}

	return writed;
}

void File::MoveCursor(u32 value, FileCursorMove cursor)
{
	if(opened == true)
	{
		DWORD dwMoveMethod = 0;

		if(cursor == FILE_CUR_BEGIN)
			dwMoveMethod = FILE_BEGIN;

		if(cursor == FILE_CUR_CURRENT)
			dwMoveMethod = FILE_CURRENT;

		if(cursor == FILE_CUR_END)
			dwMoveMethod = FILE_END;

		SetFilePointer(hFile, value, NULL, dwMoveMethod);
	}
}

bool File::IsOpened() const
{
	return opened;
}

u32 File::Read8b(u8* buffer)
{
	return Read(buffer, 1);
}
	
u32 File::Read16b(u8* buffer)
{
	return Read(buffer, 2);
}

u32 File::Read32b(u8* buffer)
{
	return Read(buffer, 4);
}

u32 File::Read64b(u8* buffer)
{
	return Read(buffer, 8);
}

u32 File::Write8b(const u8* buffer)
{
	return Write(buffer, 1);
}

u32 File::Write16b(const u8* buffer)
{
	return Write(buffer, 2);
}

u32 File::Write32b(const u8* buffer)
{
	return Write(buffer, 4);
}

u32 File::Write64b(const u8* buffer)
{
	return Write(buffer, 8);
}